package com.coderman.infosys.auth.app.facadeimpl.system;

import com.coderman.infosys.auth.app.convert.MenuConvert;
import com.coderman.infosys.auth.domain.bo.system.MenuBO;
import com.coderman.infosys.auth.domain.bo.system.SystemBO;
import com.coderman.infosys.auth.domain.enums.errors.MenuErrorEnum;
import com.coderman.infosys.auth.domain.factory.SystemFactory;
import com.coderman.infosys.auth.domain.gataway.SystemModuleQueryGataWay;
import com.coderman.infosys.auth.domain.repository.SystemModuleRepository;
import com.coderman.infosys.plat.auth.common.dto.PageDTO;
import com.coderman.infosys.plat.auth.common.dto.ResultDataDto;
import com.coderman.infosys.auth.api.facade.system.MenuFacade;
import com.coderman.infosys.auth.api.dto.system.request.UpdateMenuRequestDTO;
import com.coderman.infosys.auth.api.dto.system.MenuDTO;
import com.coderman.infosys.plat.auth.common.page.PageBO;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;


/**
 * @Description:接口实现类
 * @Author：
 * @CreateTime：2022-01-02 15:27:39
 * @version v1.0
 */
@Service
public class MenuFacadeImpl   implements MenuFacade{

    @Autowired
    private SystemModuleRepository systemModuleRepository;

    @Autowired
    private SystemFactory systemFactory;

    @Autowired
    private SystemModuleQueryGataWay systemModuleQueryGataWay;

    @Override
    public ResultDataDto<Boolean> registMenu(MenuDTO menuDTO){
        MenuBO menuBO = MenuConvert.INSTANCE.dto2bo(menuDTO);
        //构建一个聚合根对象,聚合根的构建过程在systemFactory中,在主流程中屏蔽构建过程
        SystemBO systemBO = systemFactory.initSystemByMenu(menuBO);
        systemModuleRepository.registSystemMeta(systemBO);
        return ResultDataDto.success(true);
    }

    @Override
    public ResultDataDto<PageDTO> getMenuPageList(PageDTO pageDTO){
        PageBO pageBO = pageDTO.convertToBO();
        List<MenuBO> menuBOList = systemModuleQueryGataWay.queryMenuPage(pageBO);
        List<MenuDTO> menuDTOList = MenuConvert.INSTANCE.menuBOs2dtoList(menuBOList);
        return ResultDataDto.success(pageDTO.initData(menuDTOList,pageBO.getTotalRows()));
    }

    @Override
    public ResultDataDto<MenuDTO> getByMenuCode(String menuCode){
        //这种的是否需要从聚合根中遍历得到一个MenuBO,其实很明显的是不需要,所以这种看着理所当然的查询其实可能不太符合DDD的聚合理念
        //所以这种通过简单的方式获取聚合根内部的对象，如果只是读的话那么可以从systemModuleRepository直接得到单条数据，
        //但是需要注意的是systemModuleRepository的定位是对聚合根的写，所以这种简单的方式获取聚合内部的对象其实看能否控制住读在
        //systemModuleRepository中的复杂度

        //另外一方面可以通过systemModuleQueryGataWay查询网关来查
        //区别在于其他的聚合根对象或者服务类如果要调用这个单独的获取Sytem聚合根内部的menu对象的接口其实就违反了对象聚合遍历的规则了
        //假设外部聚合根只拥有这个内部聚合对象的code，是因为某种性能问题在底层数据模型上做的删减,导致外部聚合根存在只有menuCode的情况，那么外部聚合根如果要访问这个对象
        //一般来说就是直接调用mapper或者这个MenuService,或者systemModuleQueryGataWay,当然越是顶层的接口在模块间调用就更容易解决耦合，但是这明显不符合聚合的理念，
        //如何来平衡这种变化，重点在于外部聚合需要依赖这个聚合内部的这个对象做什么，也就是说有读和写两种情况
        //1.外部聚合读自己 然后读这个聚合内部的对象,只读
        //2.外部聚合读或者写自己，然后读这个聚合内部的对象,读写都有
        //3.外部聚合读写自己，同时读写这个聚合内部的对象,同样读写都有
        //从上面的分析可以看出外部聚合只读内部对象的情况其实还稍微能接受一点。对于需求变化的兼容性会好一点。
        //当然存在一种情况就是我外部虽然需要根据聚合根内部的某个对象标示去读，但是可能要多读一点数据或者读少了数据，那就需要在读接口上做专门的处理了。

        //所以一旦出现这种绕过聚合根的方式去读聚合根内部对象的情况就需要谨慎的对待。

        //经过对这个方法的整个调用接口链路的分析我们假设这个接口是对内部web系统提供的，因此我们需要一整个对象的信息

        //这里可以通过缓存来加速,当然SystemCache是在auth-infrast模块,作为独立类使用模版方法模式来管理缓存对象，由于不是跨层调用的，所以这里
        //可以将SystemCache等抽象一个缓存接口类似于查询网关,然后应用层可以在直接调用缓存服务类控制缓存能力，
        //所以缓存逻辑可能会被内置于getMenuBO方法中
        MenuBO menuBO = systemModuleRepository.getMenuBO(menuCode);
        if(menuBO == null){
            return ResultDataDto.fail(MenuErrorEnum.MENU_NOT_FUND);
        }
        return ResultDataDto.success(MenuConvert.INSTANCE.bo2dto(menuBO));
    }

    @Override
    public ResultDataDto<Boolean> updateMenu(UpdateMenuRequestDTO dto){
        MenuBO menuBO = MenuConvert.INSTANCE.dto2bo(dto);
        //构建一个聚合根对象,聚合根的构建过程在systemFactory中,在主流程中屏蔽构建过程
        SystemBO systemBO = systemFactory.initSystemByMenu(menuBO);
        systemModuleRepository.updateSystemMeta(systemBO);

        return ResultDataDto.success();
    }

}